package cn.net.susan.generate.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.velocity.VelocityContext;
import cn.net.susan.generate.config.GenConfig;
import cn.net.susan.generate.domain.ColumnInfo;
import cn.net.susan.generate.domain.TableInfo;

/**
 * 代码生成器 工具类
 *
 * @author sue
 */
public class GenUtils {

    /**
     * mybatis空间路径
     */
    private static final String MYBATIS_PATH = "/mapper";

    /**
     * html空间路径
     */
    private static final String TEMPLATES_PATH = "views";

    private static final String JAVA_PATH = "java";

    private static final String API_PATH = "api";

    private static  final  String Entity_PATH = "model";

    /**
     * 类型转换
     */
    public static Map<String, String> javaTypeMap = new HashMap<String, String>();

    /**
     * 设置列信息
     */
    public static List<ColumnInfo> transColums(List<ColumnInfo> columns) {
        // 列信息
        List<ColumnInfo> columsList = new ArrayList<>();
        for (ColumnInfo column : columns) {
            // 列名转换成Java属性名
            String attrName = StringUtils.convertToCamelCase(column.getColumnName());
            column.setAttrName(attrName);
            column.setAttrname(StringUtils.uncapitalize(attrName));
            column.setExtra(column.getExtra());

            String columnComment = column.getColumnComment();
            if( columnComment != null ){
                String[] commentList = columnComment.split(" - ");
                column.setColumnChineseName(commentList[0]);
            }

            // 列的数据类型，转换成Java类型
            String attrType = javaTypeMap.get(column.getDataType());
            column.setAttrType(attrType);

            columsList.add(column);
        }
        return columsList;
    }

    /**
     * 获取模板信息
     *
     * @return 模板列表
     */
    public static VelocityContext getVelocityContext(String author, String packageName, TableInfo table) {

        // java对象数据传递到模板文件vm
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("tableName", table.getTableName());
        velocityContext.put("TABLENAME", table.getTableName().replaceAll("_", "-"));
        velocityContext.put("tableComment", replaceKeyword(table.getTableComment()));
        velocityContext.put("primaryKey", table.getPrimaryKey());
        velocityContext.put("className", table.getClassName());
        velocityContext.put("classname", table.getClassname());
        velocityContext.put("moduleName", getModuleName(packageName));
        velocityContext.put("columns", table.getColumns());
        velocityContext.put("basePackage", packageName);
        velocityContext.put("package", packageName);
        velocityContext.put("author", author);
        velocityContext.put("datetime", now());

        //设置表名
        String tableComment = table.getTableComment();
        if( tableComment != null ){
            String[] commentList = tableComment.split(" - ");
            table.setTableChineseName(commentList[0]);
        }
        velocityContext.put("tableChineseName", table.getTableChineseName());

        System.out.println("table.getClassname(): "+table.getClassname());

        String prefix = table.getClassName().substring(0, 3);
        prefix = prefix.toLowerCase();
        velocityContext.put("prefix", prefix);


        //for example: UmsUserInfo
        String ClassName = table.getClassName();

        //for example: umsUserInfo
        String classname = table.getClassname();

        //for example: userInfo
        String sclassname =  table.getClassname().replaceFirst("ums|fms|tms|rms|dms|sys", "");
        sclassname = sclassname.substring(0,1).toLowerCase() + sclassname.substring(1);
        velocityContext.put("sclassname", sclassname);

        //for example: UserInfo
        String SClassName = table.getClassName().replaceFirst("Ums|Fms|Tms|Rms|Dms|Sys", "");
        velocityContext.put("SClassName",SClassName);
        System.out.println("~~~~~~~~~:"+table.getClassname().replaceFirst("ums|fms|tms|rms|dms|sys", ""));

        String controllerClassName = SClassName+"Controller";
        String controllerInstanceName = sclassname+"Controller";
        String serviceClassName = SClassName+"Service";;
        String serviceInstanceName = sclassname+"Service";
        String serviceImplClassName = SClassName+"ServiceImpl";
        String serviceImplInstanceName= sclassname+"ServiceImpl";
        String mapperClassName = SClassName+"Mapper";;
        String mapperInstanceName = sclassname+"Mapper";

        String queryClassName = ClassName+"Query";
        String queryInstanceName = classname+"Query";
        String voClassName = ClassName+"Vo";
        String voInstanceName =  classname+"Vo";
        String entityClassName =  ClassName+"Entity";
        String entityInstanceName = classname+"Entity";

        velocityContext.put("controllerClassName",controllerClassName);
        velocityContext.put("controllerInstanceName",controllerInstanceName);
        velocityContext.put("serviceClassName",serviceClassName);
        velocityContext.put("serviceInstanceName",serviceInstanceName);
        velocityContext.put("serviceImplClassName",serviceImplClassName);
        velocityContext.put("serviceImplInstanceName",serviceImplInstanceName);
        velocityContext.put("mapperClassName",mapperClassName);
        velocityContext.put("mapperInstanceName",mapperInstanceName);
        velocityContext.put("queryClassName",queryClassName);
        velocityContext.put("queryInstanceName",queryInstanceName);
        velocityContext.put("voClassName",voClassName);
        velocityContext.put("voInstanceName",voInstanceName);
        velocityContext.put("entityClassName",entityClassName);
        velocityContext.put("entityInstanceName",entityInstanceName);

        return velocityContext;
    }

    private static String now() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.format(formatter);
    }

    /**
     * 获取模板信息
     *
     * @return 模板列表
     */
    public static List<String> getTemplates() {
        List<String> templates = new ArrayList<String>();
        templates.add("vm/java/Entity.java.vm");
        templates.add("vm/java/Query.java.vm");
        templates.add("vm/java/AddUpdateVo.java.vm");

        templates.add("vm/java/Controller.java.vm");
        templates.add("vm/java/Service.java.vm");
        templates.add("vm/java/ServiceImpl.java.vm");
        templates.add("vm/java/Mapper.java.vm");

        templates.add("vm/xml/Mapper.xml.vm");

        templates.add("vm/html/VueRemove.html.vm");
        templates.add("vm/html/VueAddUpdate.html.vm");
        templates.add("vm/html/VueList.html.vm");
        templates.add("vm/html/Api.html.vm");

        return templates;
    }

    /**
     * 表名转换成Java类名
     */
    public static String tableToJava(String tableName) {
        String autoRemovePre = GenConfig.getAutoRemovePre();
        String tablePrefix = GenConfig.getTablePrefix();
        if ("true".equals(autoRemovePre) && StringUtils.isNotEmpty(tablePrefix)) {
            tableName = tableName.replaceFirst(tablePrefix, "");
        }
        return StringUtils.convertToCamelCase(tableName);
    }

    /**
     * 获取文件名
     */
    public static String getFileName(String packageName, String template, TableInfo table, String moduleName) {

        String tableName =  table.getTableName();
        // 小写类名
        String classname = table.getClassname();
        String sclassname =  table.getClassname().replaceFirst("ums|fms|tms|rms|dms|sys", "");
        sclassname = sclassname.substring(0,1).toLowerCase() + sclassname.substring(1);

        // 大写类名
        String className = table.getClassName();
        String sclassName =  table.getClassName().replaceFirst("Ums|Fms|Tms|Rms|Dms|Sys", "");

        String javaPath =  JAVA_PATH;
        String mybatisPath = MYBATIS_PATH + "/" + moduleName + "/" + className;
        String htmlPath = TEMPLATES_PATH + "/" + classname;
        String apiPath = API_PATH;
        String entityPath = Entity_PATH;

        int index = table.getTableName().indexOf("_");
        String prefix = "";
        if( index > -1 ){
            prefix = className.substring(0, index);
            System.out.println("prefix: "+prefix);
        }
        prefix = prefix.toLowerCase();

        System.out.println("sclassName: "+sclassName);
        System.out.println("sclassname: "+sclassname);


        /**
         * 前端相关接口
         * */
        if(template.contains("VueRemove.html.vm")){
            return htmlPath+ "/" +sclassName + "Remove.vue";
        }

        if(template.contains("VueAddUpdate.html.vm")){
            return htmlPath +"/"+ sclassName  + "Add.vue";
        }

        if(template.contains("VueList.html.vm")){
            return htmlPath  +"/"+ sclassName   + "List.vue";
        }

        if(template.contains("Api.html.vm")){
            return apiPath  +"/"+ tableName.replaceAll("_", "-") + ".api.ts";
        }

        /**
         *  后台相关接口
         * */
        if (template.contains("Controller.java.vm")) {
            return javaPath + "/"+prefix+"/controller" + "/" + sclassName + "Controller.java";
        }

        if (template.contains("Service.java.vm")) {
            return javaPath + "/"+prefix+"/service" + "/" + sclassName + "Service.java";
        }

        if (template.contains("ServiceImpl.java.vm")) {
            return javaPath + "/"+prefix+"/service/impl" + "/" + sclassName + "ServiceImpl.java";
        }

        if (template.contains("Mapper.java.vm")) {
            return javaPath + "/"+prefix+"/mapper" + "/" + sclassName + "Mapper.java";
        }


        if (template.contains("Entity.java.vm")) {
            return entityPath  +"/entity" + "/"+prefix + "/" + className + "Entity" + ".java";
        }

        if(template.contains("Query.java.vm")){
            return entityPath +"/vo"+ "/"+prefix + "/" + className + "Query" + ".java";
        }

        if(template.contains("AddUpdateVo.java.vm")){
            return entityPath +"/vo" + "/"+prefix + "/" + className + "Vo" + ".java";
        }


        if (template.contains("Mapper.xml.vm")) {
            return mybatisPath + "Mapper.xml";
        }
        return null;
    }

    /**
     * 获取模块名
     *
     * @param packageName 包名
     * @return 模块名
     */
    public static String getModuleName(String packageName) {
        int lastIndex = packageName.lastIndexOf(".");
        int nameLength = packageName.length();
        String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength);
        return moduleName;
    }

    public static String getBasePackage(String packageName) {
        int lastIndex = packageName.lastIndexOf(".");
        String basePackage = StringUtils.substring(packageName, 0, lastIndex);
        return basePackage;
    }

    public static String getProjectPath(String packageName) {
        StringBuffer projectPath = new StringBuffer();
        projectPath.append("main/java/");
        projectPath.append(packageName.replace(".", "/"));
        projectPath.append("/");
        return projectPath.toString();
    }

    public static String replaceKeyword(String keyword) {
        String keyName = keyword.replaceAll("(?:表|信息|管理)", "");
        return keyName;
    }

    static {
        javaTypeMap.put("tinyint", "Integer");
        javaTypeMap.put("smallint", "Integer");
        javaTypeMap.put("mediumint", "Integer");
        javaTypeMap.put("int", "Integer");
        javaTypeMap.put("number", "Integer");
        javaTypeMap.put("integer", "integer");
        javaTypeMap.put("bigint", "Long");
        javaTypeMap.put("float", "Float");
        javaTypeMap.put("double", "Double");
        javaTypeMap.put("decimal", "BigDecimal");
        javaTypeMap.put("bit", "Boolean");
        javaTypeMap.put("char", "String");
        javaTypeMap.put("varchar", "String");
        javaTypeMap.put("varchar2", "String");
        javaTypeMap.put("tinytext", "String");
        javaTypeMap.put("text", "String");
        javaTypeMap.put("mediumtext", "String");
        javaTypeMap.put("longtext", "String");
        javaTypeMap.put("time", "Date");
        javaTypeMap.put("date", "Date");
        javaTypeMap.put("datetime", "Date");
        javaTypeMap.put("timestamp", "Date");
    }
}
